package com.rivues.module.assist.web.handler.dictionary;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.eigenbase.xom.MetaDef.Model;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.rivues.core.RivuDataContext;
import com.rivues.module.manage.web.service.AccountService;
import com.rivues.module.platform.web.exception.BusinessException;
import com.rivues.module.platform.web.handler.Handler;
import com.rivues.module.platform.web.handler.RequestData;
import com.rivues.module.platform.web.handler.ResponseData;
import com.rivues.module.platform.web.interceptor.LogIntercreptorHandler;
import com.rivues.module.platform.web.model.AnalyzerReport;
import com.rivues.module.platform.web.model.AnalyzerReportModel;
import com.rivues.module.platform.web.model.Auth;
import com.rivues.module.platform.web.model.Cube;
import com.rivues.module.platform.web.model.CubeLevel;
import com.rivues.module.platform.web.model.CubeMeasure;
import com.rivues.module.platform.web.model.DataDic;
import com.rivues.module.platform.web.model.Organ;
import com.rivues.module.platform.web.model.PublishedCube;
import com.rivues.module.platform.web.model.ReportModel;
import com.rivues.module.platform.web.model.User;
import com.rivues.module.platform.web.model.UserOrgan;
import com.rivues.module.platform.web.model.UserRole;
import com.rivues.module.report.web.model.PublishedReport;
import com.rivues.util.RivuTools;
import com.rivues.util.exception.ReportException;
import com.rivues.util.iface.authz.UserAuthzFactory;
import com.rivues.util.iface.cube.CubeFactory;
import com.rivues.util.iface.report.ReportFactory;
import com.rivues.util.local.LocalTools;
import com.rivues.util.service.cache.CacheHelper;
  
@Controller  
@RequestMapping("/{orgi}/assist/dictionary")  
public class DictionaryController extends Handler{
	private final Logger logger = LoggerFactory.getLogger(DictionaryController.class);
    @RequestMapping(value="/index" , name="index" , type="assist",subtype="dictionary")
    public ModelAndView index(HttpServletRequest request , @PathVariable String orgi , @ModelAttribute RequestData data) throws Exception{ 
    	ModelAndView modelView = request(super.createAssistTempletResponse("/pages/assist/dictionary/index") , orgi) ;
    	DetachedCriteria criteria = DetachedCriteria.forClass(CubeMeasure.class).add(Restrictions.eq("orgi",orgi));
    	modelView = page(request, orgi, modelView, criteria, "beginNum", "endNum", "datalist");
    	return modelView;
    }
    
    @RequestMapping(value="/list" , name="list" , type="assist",subtype="dictionary")
    public ModelAndView list(HttpServletRequest request , @PathVariable String orgi , @Valid String type) throws Exception{ 
    	ModelAndView modelView = request(super.createAssistTempletResponse("/pages/assist/dictionary/index") , orgi) ;
    
    	DetachedCriteria criteria = null;
    	if(type!=null&&type.equals("dim")){
    		criteria = DetachedCriteria.forClass(CubeLevel.class).add(Restrictions.eq("orgi",orgi));
    	}else{
    		criteria = DetachedCriteria.forClass(CubeMeasure.class).add(Restrictions.eq("orgi",orgi));
    	}
    	
    	String keyword = request.getParameter("keyword");
    	if(!StringUtils.isBlank(keyword)){
    		criteria.add(Restrictions.like("name", keyword,MatchMode.ANYWHERE).ignoreCase());
    		modelView.addObject("keyword",keyword);
    	}
    	modelView = page(request, orgi, modelView, criteria, "beginNum", "endNum", "datalist");
    	modelView.addObject("type",type);
    	return modelView;
    }
    
    @RequestMapping(value="/report" , name="list" , type="assist",subtype="replist")
    public ModelAndView report(HttpServletRequest request , @PathVariable String orgi , @Valid String type , @Valid String id , @Valid String name) throws Exception{ 
    	ModelAndView modelView = request(super.createAssistTempletResponse("/pages/assist/dictionary/reportlist") , orgi) ;
    
    	DetachedCriteria criteria = null;
    	if(type!=null&&type.equals("dim")){
    		criteria = DetachedCriteria.forClass(ReportModel.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.or(Restrictions.like("rowdimension", id , MatchMode.ANYWHERE), Restrictions.like("coldimension", id  , MatchMode.ANYWHERE)) );;
    	}else{
    		criteria = DetachedCriteria.forClass(ReportModel.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.like("measure", id , MatchMode.ANYWHERE));
    	}
    	
    	String keyword = request.getParameter("keyword");
    	
    	if(!StringUtils.isBlank(keyword)){
    		criteria.add(Restrictions.like("name", keyword,MatchMode.ANYWHERE).ignoreCase());
    		modelView.addObject("keyword",keyword);
    	}
    	modelView = page(request, orgi, modelView, criteria, "beginNum", "endNum", "datalist");
    	modelView.addObject("type",type);
    	modelView.addObject("name",name);
    	modelView.addObject("id",id);
    	return modelView;
    }

    
    @RequestMapping(value="/report/cube" , name="list" , type="assist",subtype="cube")
    public ModelAndView report_cube(HttpServletRequest request , @PathVariable String orgi , @Valid String type , @Valid String id , @Valid String name) throws Exception{ 
    	ModelAndView modelView = request(super.createAssistTempletResponse("/pages/assist/dictionary/reportlist") , orgi) ;
    
    	DetachedCriteria criteria = DetachedCriteria.forClass(ReportModel.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("cube", id));
    	
    	String keyword = request.getParameter("keyword");
    	
    	if(!StringUtils.isBlank(keyword)){
    		criteria.add(Restrictions.like("name", keyword,MatchMode.ANYWHERE).ignoreCase());
    		modelView.addObject("keyword",keyword);
    	}
    	modelView = page(request, orgi, modelView, criteria, "beginNum", "endNum", "datalist");
    	modelView.addObject("type",type);
    	modelView.addObject("name",name);
    	modelView.addObject("id",id);
    	
    	modelView.addObject("cube","cube");
    	
    	return modelView;
    }
    
    @RequestMapping(value="/report/view" , name="dictionarydetail" , type="assist",subtype="repview")
    public ModelAndView reportview(HttpServletRequest request , @PathVariable String orgi ,  @Valid String id) throws Exception{ 
    	ModelAndView modelView = request(new ResponseData("/pages/assist/dictionary/reportdetail") , orgi) ;
    	
    	List<ReportModel> list = super.getService().findAllByCriteria(DetachedCriteria.forClass(ReportModel.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("id", id))) ;
    	
    	if(list.size()>0){
    		ReportModel reportModel = list.get(0) ;
    		PublishedReport report = ReportFactory.getReportInstance().getReportByID(super.getUser(request), orgi, reportModel.getReportid() , true) ;
    		modelView.addObject("report", report) ;
    		
    		//获取报表引用的数据模型信息
    		AnalyzerReport analyzerReport = report.getReport() ;
        	AnalyzerReportModel model = null ;
        	if(analyzerReport!=null && analyzerReport.getModel()!=null && analyzerReport.getModel().size()>0){
        		model = analyzerReport.getModel().get(0);
        	}
    		
    		PublishedCube publishedCube = CubeFactory.getCubeInstance().getCubeByID(model.getPublishedcubeid()) ;
			if(publishedCube!=null){
				Cube cube = publishedCube.getCube(RivuDataContext.getUser(request)) ;
				modelView.addObject("cube", cube) ;
			}
    		
    		
    		List<DataDic> dicList = ReportFactory.getReportInstance().getAllReportDicList(orgi, super.getUser(request), RivuDataContext.TabType.PUB.toString()) ;
    		DataDic dataDic = null ;
    		
    		for(DataDic dic : dicList){
				if(dic.getId().equals(report.getDicid())){
					dataDic = dic ;
				}
			}
    		
    		
    		DetachedCriteria criteria = DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("resourceid", report.getId())) ;
    		
    		List<Auth> authList = super.getService().findAllByCriteria(criteria) ;
    		
    		
    		
    		if(dataDic != null && !"true".equals(report.getUseacl())){
    			int dept = 0 ;
    			if(!"0".equals(dataDic.getParentid())){
    				addReportAuth(authList  , dataDic , super.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("resourceid", dataDic.getId())))) ;
		    		if(!"true".equals(dataDic.getType())){
	    				while(dataDic != null && !"0".equals(dataDic.getParentid()) && dept <20){
			    			dept ++; 
			    			for(DataDic dic : dicList){
			    				if(dic.getId().equals(dataDic.getParentid())){
			    					addReportAuth(authList , dic , super.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("resourceid", dic.getId())))) ;
			    					dataDic = dic ;
			    				}
			    				if("true".equals(dataDic.getType())){
			    					dataDic = null ;
			    				}
			    			}
			    		}
		    		}
    			}else{
    				addReportAuth(authList , dataDic , super.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("resourceid", dataDic.getId())))) ;
    				if(!"true".equals(dataDic.getType())){
    					addReportAuth(authList , null , super.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("resourceid", "0")))) ;
    				}
    			}
    		}else{
    			addReportAuth(authList , null , super.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("resourceid", "0")))) ;
    		}
    		modelView.addObject("authlist", authList) ; 
    	}
    	
    	return modelView;
    }
    
    private void addReportAuth(List<Auth> rootList , DataDic dic , List<Auth> dicAuthList){
    	for(Auth auth : dicAuthList){
    		boolean found = false ;
    		for(Auth rootAuth : rootList){
    			if(rootAuth.getOwnerid().equals(auth.getOwnerid())){
    				found = true ;break ;
    			}
    		}
    		if(!found){
    			auth.setParent(true); 
    			if(dic == null){
    				auth.setParentdic("公共文件夹") ; 
    				auth.setParentdicid("0");
    			}else{
    				auth.setParentdic(dic.getName()) ;
    				auth.setParentdicid(dic.getId());
    			}
    			rootList.add(auth) ;
    		}
    	}
    }


    
    @RequestMapping(value="/dictionarydetail/{type}/{id}" , name="dictionarydetail" , type="assist",subtype="dictionary")
    public ModelAndView dictionarydetail(HttpServletRequest request , @PathVariable String orgi , @PathVariable String type, @PathVariable String id) throws Exception{ 
    	ModelAndView modelView = request(new ResponseData("/pages/assist/dictionary/dictionarydetail") , orgi) ;
    	Object data = null;
    	Cube cube = null;
    	if(type!=null&&type.equals("dim")){
    		CubeLevel level = (CubeLevel)super.getService().getIObjectByPK(CubeLevel.class, id);
    		cube = level.getCube();
    		data = level;
    	}else{
    		CubeMeasure measure = (CubeMeasure)super.getService().getIObjectByPK(CubeMeasure.class, id);
    		cube = measure.getCube();
    		data = measure;
    	}
    	
//    	if(cube!=null){
//    		List<PublishedCube> pcubes = super.getService().findAllByCriteria(DetachedCriteria.forClass(PublishedCube.class).add(Restrictions.eq("dataid", cube.getId())));
//    		List<PublishedReport> reports = new ArrayList<PublishedReport>();
//    		if(pcubes!=null&&pcubes.size()>0){
//    			for (PublishedCube pcube : pcubes) {
//    				reports.addAll(super.getService().findAllByCriteria(DetachedCriteria.forClass(PublishedReport.class).add(Restrictions.eq("dataid", cube.getId()))));
//				}
//    		}
//    	}
    	
    	modelView.addObject("data", data);
    	modelView.addObject("type", type);

    	return modelView;
    }
    
    
   
    
} 